package pl.edu.pk.mech.kkbus.controller;

import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import javax.validation.ConstraintViolation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import pl.edu.pk.mech.kkbus.component.MyValidator;
import pl.edu.pk.mech.kkbus.model.ResponseStatus;
import pl.edu.pk.mech.kkbus.service.UserService;
import pl.edu.pk.mech.kkbus.service.ExchangeService;
import pl.edu.pk.mech.kkbus.dto.NewUser;
import pl.edu.pk.mech.kkbus.dto.AuthenticatedUser;
import pl.edu.pk.mech.kkbus.dto.UserWithRole;
import pl.edu.pk.mech.kkbus.dto.ManageUser;
import pl.edu.pk.mech.kkbus.dto.Exchange;
import pl.edu.pk.mech.kkbus.entities.User;

@Controller
public class UserController extends RestController {
    
    private static final Logger log = Logger.getLogger(UserController.class.getName());
    
    @Autowired
    UserService userService;
    
    @Autowired
    ExchangeService exchangeService;
    
    @Autowired
    MyValidator validatorComponent;
    
    @RequestMapping(value = "/users/role/{role}", method = RequestMethod.GET)
    public @ResponseBody List<UserWithRole> getUsers(@PathVariable String role) {  
        log.info("Get users with role " + role);
        User.Role enumRole;
        try {
            enumRole = User.Role.valueOf(role);
        } catch (IllegalArgumentException e) {
            return null;
        }
        
        return userService.getUsersByRole(enumRole);
    } 
    
    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public @ResponseBody ResponseStatus create(@RequestBody NewUser user) { 
        log.info("Request for create new user!");
        
        boolean validation = true;
        
        Set<ConstraintViolation<NewUser>> violations = validatorComponent.
                getValidatorInstance().validate(user);
        for (ConstraintViolation<NewUser> violation : violations) {
            validation = false;
            
            String propertyPath = violation.getPropertyPath().toString();
            String message = violation.getMessage();
            
            log.info(propertyPath + " " + message);
        }
        
        if (validation) {
            log.info("Successful validation!");
            boolean result = userService.createUser(user);
            
            return result ? ResponseStatus.ADDED : ResponseStatus.ERROR;
        } else {
            log.info("Incorrect validation!");
            return null;
        }
    }
    
    @RequestMapping(value = "/user/authenticated", method = RequestMethod.GET)
    public @ResponseBody AuthenticatedUser getaAthenticatedUser() {
        String principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();        
        return userService.getAuthenticatedUser(principal);
    } 
    
    @RequestMapping(value = "/user/activate/{hash}", method = RequestMethod.GET)
    public @ResponseBody ResponseStatus activate(@PathVariable String hash) {
        log.info("Activate user with hash: " + hash);        
        boolean result = userService.activateUser(hash);    
        return (result == true) ? ResponseStatus.SUCCESS : ResponseStatus.ERROR;
    }
    
    @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    public @ResponseBody ResponseStatus deleteUser(@PathVariable long id) {
        boolean result = userService.deleteUser(id);   
        return (result == true) ? ResponseStatus.DELETED : ResponseStatus.ERROR;
    }
    
    // For update, ban, unban user
    @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
    public @ResponseBody ResponseStatus editUser(@PathVariable long id, @RequestBody ManageUser user) {
        // TODO Validation like in create
        
        boolean result = false;
        
        if (user.getAction().equals("BAN")) {
            result = userService.banOrUnbanUser(id, true);
            return result ? ResponseStatus.SUCCESS : ResponseStatus.ERROR;
            
        } else if (user.getAction().equals("UNBAN")) { 
            result = userService.banOrUnbanUser(id, false);
            return result ? ResponseStatus.SUCCESS : ResponseStatus.ERROR;
            
        } else if (user.getAction().equals("UPDATE")) {
            log.info("Updating user with id " + id);
            result = userService.updateUser(id, user);
            return result ? ResponseStatus.UPDATED : ResponseStatus.ERROR;
        } else {
            return ResponseStatus.ERROR;
        }   
        
    } 
    
    // Exchange
    
    @RequestMapping(value = "/exchange", method = RequestMethod.POST)
    public @ResponseBody ResponseStatus createUser(@RequestBody Exchange exchange) {  
        log.info("Exchange for user: " + exchange.getUserId() + " and award " + exchange.getAwardId());
        
        boolean result = exchangeService.createExchange(exchange);

        return result ? ResponseStatus.SUCCESS : ResponseStatus.ERROR;
    } 
    
    @RequestMapping(value = "/exchange/user/{id}", method = RequestMethod.GET)
    public @ResponseBody List<Exchange> getExchangesForUser(@PathVariable long id) {
        log.info("Get exchanges for user " + id);
        return exchangeService.getExchangesForUser(id);
    }
    
    @RequestMapping(value = "/exchange/{id}", method = RequestMethod.DELETE)
    public @ResponseBody ResponseStatus delete(@PathVariable long id) {
        boolean result = exchangeService.delete(id);
        return result ? ResponseStatus.DELETED : ResponseStatus.ERROR;
    }
}
